/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "WindowCreator.h"
#include "Gluck.h"

namespace liba
{

WindowMessageListener::WindowMessageListener( WindowCreator * creator ):
	creator( creator )
{
	creator->listeners.push_back( this );
}

WindowMessageListener::~WindowMessageListener()
{
	creator->listeners.remove( this );
}

int WindowMessageListener::window_proc( unsigned msg, unsigned wParam, unsigned lParam )
{
	return 0;
}

#ifndef MAC_VERSION
LRESULT WindowCreator::WindowProc( HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	WindowCreator * app = reinterpret_cast<WindowCreator *>( GetWindowLong(wnd, GWL_USERDATA) );
	if( app )
		return app->window_proc( msg, wParam, lParam );
	return DefWindowProc( wnd, msg, wParam, lParam);
}
#endif

WindowCreator::WindowCreator(const WindowImpl * parent, unsigned window_style)
{
#ifdef MAC_VERSION
	throw Gluck( __FUNCTION__, "unimplemented" );
#else
	HINSTANCE instance = GetModuleHandle(NULL);
	WNDCLASS wc;
	wc.style = 0;
	wc.lpfnWndProc = WindowCreator::WindowProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = instance;
	wc.hIcon = LoadIcon( instance, MAKEINTRESOURCE(102)); // BUG - constant in code
	wc.hCursor = LoadCursor( NULL, IDC_ARROW );
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName = 0;
	wc.lpszClassName = "liba::WindowsCreator";
	RegisterClass( &wc );

	HWND parent_wnd = parent->get_wnd();
	RECT rc;
	GetWindowRect( parent_wnd, &rc );

	HWND wnd = CreateWindowEx(
		0,
		"liba::WindowsCreator",
		"Loading...",
		window_style,
		0, 0,
		(rc.right-rc.left), (rc.bottom-rc.top),
		parent_wnd, NULL, instance, NULL );

	impl.reset(new WindowImpl( instance, wnd ));
	if( !impl.get() )
		throw Gluck(__FUNCTION__, "Could not create mwin window");
	SetWindowLong( wnd, GWL_USERDATA, reinterpret_cast<long>( this ) );
#endif
}

WindowCreator::WindowCreator( int sx, int sy, bool resizeable )
{
#ifdef MAC_VERSION
	//TODO:
	sx = 1024;
	sy = 768;
	GDHandle main_device;
	main_device = GetMainDevice();
	int left = ((**main_device).gdRect.right - sx)/2;
	int top = ((**main_device).gdRect.bottom - sy)/2;
	Rect rect;
	SetRect( &rect, left, top, sx, sy );
	RGBColor rgb = { 0, 0, 0 };
	WindowRef window = 0;
	CreateNewWindow( kDocumentWindowClass, kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute |
					kWindowResizableAttribute, &rect, &window );

	impl.reset(new WindowImpl( window ));
	if( !impl.get() )
		throw Gluck(__FUNCTION__, "Could not create mwin window");
#else
	HINSTANCE instance = GetModuleHandle(NULL);
	WNDCLASS wc;
	wc.style = 0;
	wc.lpfnWndProc = WindowCreator::WindowProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = instance;
	wc.hIcon = LoadIcon( instance, MAKEINTRESOURCE(102)); // BUG - constant in code
	wc.hCursor = LoadCursor( NULL, IDC_ARROW );
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName = 0;
	wc.lpszClassName = "liba::WindowsCreator";
	RegisterClass( &wc );

//    LONG window_style = WS_OVERLAPPEDWINDOW;
	LONG window_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
	if( !resizeable )
	{
		window_style &= ~WS_MAXIMIZEBOX;
		window_style &= ~WS_THICKFRAME;
	}
	// Set the window's initial width
	RECT rc;
	rc.left = 0;
	rc.top = 0;
	rc.right = sx;
	rc.bottom = sy;
	AdjustWindowRect( &rc, window_style, true );

	HWND wnd = CreateWindowEx(
		0,
		"liba::WindowsCreator",
		"Loading...",
		window_style,
		0, 0,
		(rc.right-rc.left), (rc.bottom-rc.top),
		NULL, NULL, instance, NULL );

	impl.reset(new WindowImpl( instance, wnd ));
	if( !impl.get() )
		throw Gluck(__FUNCTION__, "Could not create mwin window");
	SetWindowLong( wnd, GWL_USERDATA, reinterpret_cast<long>( this ) );
#endif
}

WindowCreator::WindowCreator(WindowImpl * win)
{
	impl.reset(win);
}

WindowCreator::~WindowCreator()
{
#ifdef MAC_VERSION
	DisposeWindow( impl->get_wnd() );
#else
	DestroyWindow( impl->get_wnd() );
#endif
}

WindowImpl * WindowCreator::get_window()const
{
	return impl.get();
}

#ifndef MAC_VERSION
int WindowCreator::window_proc( unsigned msg, unsigned wParam, unsigned lParam )
{
	Listeners::iterator it=listeners.begin();
	for( ;it != listeners.end(); ++it )
	{
		int res = (*it)->window_proc( msg, wParam, lParam );
		if( res )
			return res;
	}
	return DefWindowProc( get_window()->get_wnd(), msg, wParam, lParam );
}
#endif

}// namespace liba


